package service

import (
	"context"
	"errors"
	"gitee.com/sunny-zhangqiang/zcache/config"
	"gitee.com/sunny-zhangqiang/zcache/xhttp"
	"sync"
	"time"
)

var service *Service

type Service struct {
	conf    *config.Server
	servers []*xhttp.Server
}

// StartService  int & ListenAndServe service
// 仅在初始化阶段可以调用
func StartService(conf *config.Server) error {
	var srv = &Service{
		conf: conf,
	}

	if len(conf.Listeners) == 0 {
		return errors.New("no listeners")
	}

	servers := make([]*xhttp.Server, len(conf.Listeners))
	for i := 0; i < len(conf.Listeners); i++ {
		servers[i] = &xhttp.Server{
			Addr:                      conf.Listeners[i],
			Handler:                   srv,
			ReadHeaderTimeout:         time.Duration(conf.ServerReadHeaderTimeoutMsec) * time.Millisecond,
			IdleTimeout:               time.Duration(conf.ServerIdleTimeoutMsec) * time.Millisecond,
			ReadDataTimeout:           time.Duration(conf.ServerReadDataTimeoutMsec) * time.Millisecond,
			WriteDataTimeout:          time.Duration(conf.ServerWriteDataTimeoutMsec) * time.Millisecond,
			WorkerPoolMaxWorkersCount: conf.ServerMaxWorkers,
			MaxHeaderBytes:            conf.ServerMaxHeaderBytes,
		}

		go servers[i].ListenAndServe()
	}

	srv.servers = servers

	service = srv
	return nil
}

func CloseService() error {
	if service == nil {
		panic("service no started")
	}

	ctx, cancel := context.WithTimeout(context.Background(),
		time.Duration(service.conf.QuitTimeoutSec)*time.Second)
	defer cancel()

	wg := &sync.WaitGroup{}
	wg.Add(len(service.servers))

	for i := 0; i < len(service.servers); i++ {
		go func(server *xhttp.Server) {
			server.Shutdown(ctx)
			wg.Done()
		}(service.servers[i])
	}

	wg.Wait()

	return nil
}
